package com.sunday.common.doc;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

@Slf4j
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    @Order(1)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {

        /**
         * @see OAuth2AuthorizationServerConfigurer#createConfigurers()
         */
        OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer();

        // 将默认的OAuth2端点匹配器和你的自定义匹配器合并到一个新的RequestMatcher
        RequestMatcher endpointsMatcher = new OrRequestMatcher(
                authorizationServerConfigurer.getEndpointsMatcher()
        );

        log.info("{}", endpointsMatcher);

        http
                // 只有当请求与 endpointsMatcher 匹配时，随后定义的安全配置才会被应用。这样做可以优化性能，因为不是所有的HTTP请求都需要经过授权服务器的配置。
                .securityMatcher(endpointsMatcher)
                .with(authorizationServerConfigurer, Customizer.withDefaults())
                // 定制CSRF保护的，它告诉Spring Security对于那些由 endpointsMatcher 匹配的请求，忽略CSRF保护。
                .csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher))

        ;

        return http.build();
    }

    @Bean
    @Order(2)
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(authorize -> authorize
                        .anyRequest().permitAll()
                )
        ;

        return http.build();
    }

}
